package com.sxt.sys.realm;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sxt.sys.common.ActiverUser;
import com.sxt.sys.common.Constast;
import com.sxt.sys.entity.Permission;
import com.sxt.sys.entity.User;
import com.sxt.sys.service.IPermissionService;
import com.sxt.sys.service.IRoleService;
import com.sxt.sys.service.IUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class UserRealm extends AuthorizingRealm {

    @Lazy
    @Autowired
    private IUserService userService;

    @Autowired
    @Lazy
    private IPermissionService permissionService;

    @Autowired
    @Lazy
    private IRoleService roleService;

    public String getName(){
        return this.getClass().getSimpleName();
    }


    /**
     *认证
     */

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("loginname",authenticationToken.getPrincipal().toString());
        //authenticationToken.getPrincipal()获取用户身份
        //通过用户名从数据库中查询出该用户  QueryWrapper为条件查询构造器
        User user=userService.getOne(queryWrapper);   //执行查询操作

        if (user!=null){
            ActiverUser activerUser=new ActiverUser();
            activerUser.setUser(user);
            //根据用户id去查询percode
            QueryWrapper<Permission> qw=new QueryWrapper<>();
            //设置只能查询可用菜单
            qw.eq("type", Constast.TYPE_PERMISSION);
            qw.eq("available",Constast.AVAILABLE_TRUE);
            Integer userId=user.getId();
            //根据用户id查询角色id,因为用户可能有多个角色，所有用list存放结果
            List<Integer> currentUserRoleIds=roleService.queryUserRoleIdsByUid(userId);

            //声明一个set集合来存放pids来存放查询的权限结果，用set可以去掉重复的权限结果
            Set<Integer> pids=new HashSet<>() ;
            for(Integer rid :currentUserRoleIds){
                //根据用户id查询出权限id
                List<Integer> permissionIds=roleService.queryRolePermissionIdsByRid(rid);
                pids.addAll(permissionIds);
            }
            List<Permission> list=new ArrayList<>();
            if(pids.size()>0){
                qw.in("id",pids);
                list=permissionService.list(qw);
            }
            List<String> percodes=new ArrayList<>();
            for(Permission permission:list){
                percodes.add(permission.getPercode());
            }
            //放到activityUser中
            activerUser.setPermission(percodes);
            //生成盐
            ByteSource credentialsSalt=ByteSource.Util.bytes(user.getSalt());
            /**
             * 参数说明：
             * 参数1：活动的User
             * 参数2：从数据库里面查询出来的密码(已经通过MD5加密)
             * 参数3：从数据库里面查询出来的盐
             * 参数4：当前类名
             */

            SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(activerUser,user.getPwd(),credentialsSalt,this.getName());
            return info;
        }
        return null;
    }

    /*
    * 授权*/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
        ActiverUser activerUser= (ActiverUser) principalCollection.getPrimaryPrincipal();
        User user=activerUser.getUser();
        List<String> superPermision=new ArrayList<>();
        superPermision.add("*:*");
        List<String> permissions=activerUser.getPermission();
        if(user.getType().equals(Constast.USER_TYPE_SUPER)){
            authorizationInfo.addStringPermissions((superPermision));
        }else{
            if(permissions!=null&&permissions.size()>0){
                authorizationInfo.addStringPermissions((permissions));
            }

        }
        return authorizationInfo;
    }
}
